package com.lineage.server.model;

import static com.lineage.server.model.skill.L1SkillId.*;

import java.util.Calendar;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.lineage.config.ConfigAlt;
import com.lineage.data.event.FeatureItemSet;
import com.lineage.server.ActionCodes;
import com.lineage.server.model.Instance.L1DollInstance;
import com.lineage.server.model.Instance.L1NpcInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.Instance.L1PetInstance;
import com.lineage.server.model.Instance.L1SummonInstance;
import com.lineage.server.model.poison.L1DamagePoison;
import com.lineage.server.serverpackets.S_AttackPacketPc;
import com.lineage.server.serverpackets.S_ChangeHeading;
import com.lineage.server.serverpackets.S_DoActionGFX;
import com.lineage.server.serverpackets.S_EffectLocation;
import com.lineage.server.serverpackets.S_PacketBoxDk;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.S_UseArrowSkill;
import com.lineage.server.timecontroller.server.ServerWarExecutor;

/**
 * 物理攻擊判斷項(PC)
 * @author dexc
 *
 */
public class L1AttackPc extends L1AttackMode {

	private static final Log _log = LogFactory.getLog(L1AttackPc.class);

	// 攻擊模式 0x00:none 0x02:暴擊 0x04:雙擊 0x08:鏡反射
	private byte _attackType = 0x00;
	
	public L1AttackPc(final L1PcInstance attacker, final L1Character target) {
		if (target == null) {
			return;
		}
		
		if (target.isDead()) {
			return;
		}
		
		_pc = attacker;

		if (target instanceof L1PcInstance) {
			_targetPc = (L1PcInstance) target;
			_calcType = PC_PC;

		} else if (target instanceof L1NpcInstance) {
			_targetNpc = (L1NpcInstance) target;
			_calcType = PC_NPC;
		}
		
		// 武器情報の取得
		_weapon = this._pc.getWeapon();
		if (_weapon != null) {
			_weaponId = _weapon.getItem().getItemId();
			_weaponType = _weapon.getItem().getType1();
			_weaponType2 = _weapon.getItem().getType();
			_weaponAddHit = _weapon.getItem().getHitModifier() + _weapon.getHitByMagic();
			_weaponAddDmg = _weapon.getItem().getDmgModifier() + _weapon.getDmgByMagic();

			_weaponSmall = _weapon.getItem().getDmgSmall();
			_weaponLarge = _weapon.getItem().getDmgLarge();
			_weaponRange = _weapon.getItem().getRange();
			_weaponBless = _weapon.getItem().getBless();
			
			if ((_weaponType != 20) && (_weaponType != 62)) {
				_weaponEnchant = _weapon.getEnchantLevel() - _weapon.get_durability(); // 損傷分マイナス

			} else {
				_weaponEnchant = _weapon.getEnchantLevel();
			}

			_weaponMaterial = _weapon.getItem().getMaterial();
			if (_weaponType == 20) {// 弓 武器類型:箭取回
				_arrow = _pc.getInventory().getArrow();
				if (_arrow != null) {
					_weaponBless = _arrow.getItem().getBless();
					_weaponMaterial = _arrow.getItem().getMaterial();
				}
			}
			
			if (_weaponType == 62) {// 鐵手甲 武器類型:飛刀取回
				_sting = _pc.getInventory().getSting();
				if (_sting != null) {
					_weaponBless = _sting.getItem().getBless();
					_weaponMaterial = _sting.getItem().getMaterial();
				}
			}
			
			_weaponDoubleDmgChance = _weapon.getItem().getDoubleDmgChance();
			_weaponAttrEnchantKind = _weapon.getAttrEnchantKind();
			_weaponAttrEnchantLevel = _weapon.getAttrEnchantLevel();
		}
		
		// ステータスによる追加ダメージ補正
		if (_weaponType == 20) {// 弓 增加敏捷傷害
			Integer dmg = L1AttackList.DEXD.get((int) _pc.getDex());
			if (dmg != null) {
				_statusDamage = dmg;
			}

		} else { // それ以外はＳＴＲ値参照abstract
			Integer dmg = L1AttackList.STRD.get((int) _pc.getStr());
			if (dmg != null) {
				_statusDamage = dmg;
			}
		}

		_target = target;
		_targetId = target.getId();
		_targetX = target.getX();
		_targetY = target.getY();
	}

	/**
	 * 命中判定
	 */
	@Override
	public boolean calcHit() {
		if (this._target == null) {// 物件遺失
			this._isHit = false;
			return this._isHit;
		}
		
		if (this._weaponRange != -1) {
			
			// 近距離武器攻擊距離判斷
			final int location = 
				this._pc.getLocation().getTileLineDistance(this._target.getLocation());
			
			if (location > (this._weaponRange + 1)) {
				this._isHit = false; // 射程範囲外
				return this._isHit;
			}
			
		} else {
			// 遠距離武器攻擊距離判斷
			if (!this._pc.getLocation().isInScreen(this._target.getLocation())) {
				this._isHit = false; // 射程範囲外
				return this._isHit;
			}
		}
		
		if ((this._weaponType == 20) && (this._weaponId != 190) && (this._arrow == null)) {
			this._isHit = false; // 持弓 無箭

		} else if ((this._weaponType == 62) && (this._sting == null)) {
			this._isHit = false; // 持鐵手甲 無飛刀

		} else if (!this._pc.glanceCheck(this._targetX, this._targetY)) {
			this._isHit = false; // 攻擊方向中途具有障礙

		} else if ((this._weaponId == 247) || (this._weaponId == 248) || (this._weaponId == 249)) {
			this._isHit = false; // 試煉武器

		} else if (this._calcType == PC_PC) {
			this._isHit = this.calcPcHit();// PC TO PC

		} else if (this._calcType == PC_NPC) {
			this._isHit = this.calcNpcHit();// PC TO NPC
		}
		
		return this._isHit;
	}
	
	private int str_dex_Hit() {
		int hitRate = 0;
		// 力量命中補正
		final Integer hitStr = 
				L1AttackList.STRH.get(this._pc.getStr() - 1);
		if (hitStr != null) {
			hitRate += hitStr;
			
		} else {
			hitRate += 19;
		}
		
		// 敏捷命中補正
		final Integer hitDex = 
				L1AttackList.DEXH.get(this._pc.getDex() - 1);
		if (hitDex != null) {
			hitRate += hitDex;
			
		} else {
			hitRate += 29;
		}
		return hitRate;
	}
	
	/**
	 * PC對PC的命中
	 * @return
	 */
	private boolean calcPcHit() {
		if (_targetPc == null) {
			return false;
		}
		
		// 傷害為0
		if (dmg0(_targetPc)) {
			return false;
		}

		// 迴避攻擊
		if (calcEvasion()) {
			return false;
		}

		if (_weaponType2 == 17) {// 奇古獸
			return true;
		}
		
		_hitRate = _pc.getLevel();

		// 力量命中補正 / 敏捷命中補正
		_hitRate += str_dex_Hit();

		if ((_weaponType != 20) && (_weaponType != 62)) {
			_hitRate += 
				//(this._weaponAddHit + this._pc.getHitup() + this._pc.getOriginalHitup() + (this._weaponEnchant / 2));// TEST
				(_weaponAddHit + _pc.getHitup() + _pc.getOriginalHitup() + (_weaponEnchant * 0.6));
			
		} else {
			_hitRate += 
				//(this._weaponAddHit + this._pc.getBowHitup() + this._pc.getOriginalBowHitup() + (this._weaponEnchant / 2));// TEST
				(_weaponAddHit + _pc.getBowHitup() + _pc.getOriginalBowHitup() + (_weaponEnchant * 0.6));
		}

		if ((_weaponType != 20) && (_weaponType != 62)) { // 防具による追加命中
			_hitRate += _pc.getHitModifierByArmor();

		} else {
			_hitRate += _pc.getBowHitModifierByArmor();
		}
		
		final int weight240 = _pc.getInventory().getWeight240();
		if (weight240 > 80) { // 重量による命中補正
			if ((80 < weight240) && (120 >= weight240)) {
				_hitRate -= 1;

			} else if ((121 <= weight240) && (160 >= weight240)) {
				_hitRate -= 3;

			} else if ((161 <= weight240) && (200 >= weight240)) {
				_hitRate -= 5;
			}
		}

		_hitRate += hitUp();

		//int attackerDice = _random.nextInt(20) + 1 + this._hitRate - 10;// TEST
		int attackerDice = _random.nextInt(20) + 2 + _hitRate - 10;

		// 技能增加閃避
		attackerDice += attackerDice(_targetPc);
		
		int defenderDice = 0;

		final int defenderValue = (int) (_targetPc.getAc() * 1.5) * -1;

		if (_targetPc.getAc() >= 0) {
			defenderDice = 10 - _targetPc.getAc();

		} else if (_targetPc.getAc() < 0) {
			defenderDice = 10 + _random.nextInt(defenderValue) + 1;
		}

		final int fumble = _hitRate - 9;
		final int critical = _hitRate + 10;
		if (_pc.isDragonKnight()) {
			attackerDice *= 1.01;
		}
		if (_pc.isElf()) {
			if (_pc.getElfAttr() == 2) {
				attackerDice *= 1.02;
			}
		}

		if (attackerDice <= fumble) {
			_hitRate = 15;

		} else if (attackerDice >= critical) {
			_hitRate = 100;

		} else {
			if (attackerDice > defenderDice) {
				_hitRate = 100;
				
			} else if (attackerDice <= defenderDice) {
				_hitRate = 15;
			}
		}

		final int rnd = _random.nextInt(100) + 1;
		if (_weaponType == 20) {// 弓 附加ER計算
			if (_hitRate > rnd) {
				return calcErEvasion();
			}
		}
		return _hitRate >= rnd;
	}

	/**
	 * PC對NPC的命中
	 * @return
	 */
	private boolean calcNpcHit() {
		// 對不可見的怪物額外判斷
		final int gfxid = this._targetNpc.getNpcTemplate().get_gfxid();
		switch (gfxid) {
		case 2412:// 南瓜的影子
			if (!_pc.getInventory().checkEquipped(20046)) {// 南瓜帽
				return false;
			}
			break;
		}
		
		// 傷害為0
		if (dmg0(_targetNpc)) {
			return false;
		}

		if (_weaponType2 == 17) {// 奇古獸 命中100%
			return true;
		}
		
		// ＮＰＣへの命中率
		// ＝（PCのLv＋クラス補正＋STR補正＋DEX補正＋武器補正＋DAIの枚数/2＋魔法補正）×5−{NPCのAC×（-5）}
		_hitRate = _pc.getLevel();

		// 力量命中補正 / 敏捷命中補正
		_hitRate += str_dex_Hit();

		if ((_weaponType != 20) && (_weaponType != 62)) {
			_hitRate += 
				//(this._weaponAddHit + this._pc.getHitup() + this._pc.getOriginalHitup() + (this._weaponEnchant / 2)); // XXX
				(_weaponAddHit + _pc.getHitup() + _pc.getOriginalHitup() + (_weaponEnchant * 0.6));

		} else {
			_hitRate += 
				//(this._weaponAddHit + this._pc.getBowHitup() + this._pc.getOriginalBowHitup() + (this._weaponEnchant / 2));// XXX
				(_weaponAddHit + _pc.getBowHitup() + _pc.getOriginalBowHitup() + (_weaponEnchant * 0.6));
		}

		if ((_weaponType != 20) && (_weaponType != 62)) { // 防具による追加命中
			_hitRate += _pc.getHitModifierByArmor();

		} else {
			_hitRate += _pc.getBowHitModifierByArmor();
		}

		final int weight240 = _pc.getInventory().getWeight240();
		if (weight240 > 80) { // 重量による命中補正
			if ((80 < weight240) && (120 >= weight240)) {
				_hitRate -= 1;

			} else if ((121 <= weight240) && (160 >= weight240)) {
				_hitRate -= 3;

			} else if ((161 <= weight240) && (200 >= weight240)) {
				_hitRate -= 5;
			}
		}
		
		_hitRate += hitUp();

		//int attackerDice = _random.nextInt(20) + 1 + this._hitRate - 10;// TEST
		int attackerDice = _random.nextInt(20) + 2 + _hitRate - 10;

		// 技能增加閃避
		attackerDice += attackerDice(_targetNpc);
		
		final int defenderDice = 10 - _targetNpc.getAc();

		final int fumble = _hitRate - 9;
		final int critical = _hitRate + 10;
		if (_pc.isDragonKnight()) {
			attackerDice *= 1.01;
		}
		if (_pc.isElf()) {
			if (_pc.getElfAttr() == 2) {
				attackerDice *= 1.02;
			}
		}
		
		if (attackerDice <= fumble) {
			_hitRate = 15;

		} else if (attackerDice >= critical) {
			_hitRate = 100;

		} else {
			if (attackerDice > defenderDice) {
				_hitRate = 100;
				
			} else if (attackerDice <= defenderDice) {
				_hitRate = 15;
			}
		}

		final int npcId = _targetNpc.getNpcTemplate().get_npcId();
		
		final Integer tgskill = L1AttackList.SKNPC.get(npcId);
		if (tgskill != null) {
			if (!_pc.hasSkillEffect(tgskill)) {
				_hitRate = 0;
			}
		}

		final Integer tgpoly = L1AttackList.PLNPC.get(npcId);
		if (tgpoly != null) {
			if (tgpoly.equals(_pc.getTempCharGfx())) {
				_hitRate = 0;
			}
		}

		final int rnd = _random.nextInt(100) + 1;

		return _hitRate >= rnd;
	}

	/**
	 * 追加命中
	 * @return
	 */
	private int hitUp() {
		int hitUp = 0;
		if (_pc.getSkillEffect().size() <= 0) {
			return hitUp;
		}

		if (!_pc.getSkillisEmpty()) {
			try {
				// 追加命中(近距離武器)
				if ((_weaponType != 20) && (_weaponType != 62)) {
					for (final Integer key : _pc.getSkillEffect()) {
						final Integer integer = L1AttackList.SKU1.get(key);
						if (integer != null) {
							hitUp += integer;
						}
					}
					
				// 追加命中(遠距離武器)
				} else {
					for (final Integer key : _pc.getSkillEffect()) {
						final Integer integer = L1AttackList.SKU2.get(key);
						if (integer != null) {
							hitUp += integer;
						}
					}
				}
				
			} catch (final ConcurrentModificationException e) {
				// 技能取回發生其他線程進行修改
			} catch (final Exception e) {
				_log.error(e.getLocalizedMessage(), e);
			}
		}
		
		return hitUp;
	}

	/**
	 * 傷害計算
	 */
	@Override
	public int calcDamage() {
		switch (_calcType) {
		case PC_PC:
			_damage = calcPcDamage();
			break;

		case PC_NPC:
			_damage = calcNpcDamage();
			break;
		}
		if (_damage > 0) {
			// 特殊魔法武器
			if (_weapon != null) {
				if (FeatureItemSet.POWER_START) {
					final L1AttackPower attackPower = new L1AttackPower(_pc, _target, _weaponAttrEnchantKind, _weaponAttrEnchantLevel);
					_damage = attackPower.set_item_power(_damage);
				}
			}
		}
		return _damage;
	}

	/**
	 * 傷害質初始化
	 * @param weaponMaxDamage 可發出的最大攻擊質
	 * @return
	 */
	private int weaponDamage1(int weaponMaxDamage) {
		int weaponDamage = 0;
		//boolean soulFlame = false;// 技能(烈焰之魂)
		// 武器類型核心分類
		switch (_weaponType2) {
		case 0:// 空手
		case 4:// 弓
		case 10:// 鐵手甲
		case 13:// 弓(單手)
			break;

		case 11:// 鋼爪
			if ((_random.nextInt(100) + 1) <= _weaponDoubleDmgChance) {
				weaponDamage  = weaponMaxDamage;
				_attackType = 0x02;
			}
			break;

		case 15:// 雙手斧
		case 1:// 劍
		case 2:// 匕首
		case 3:// 雙手劍
		case 5:// 矛(雙手)
		case 6:// 斧(單手)
		case 7:// 魔杖
		case 8:// 飛刀
		case 9:// 箭
		case 12:// 雙刀
		case 14:// 矛(單手)
		case 16:// 魔杖(雙手)
		case 17:// 奇古獸
		case 18:// 鎖鏈劍
			weaponDamage = _random.nextInt(weaponMaxDamage) + 1;
			break;
		}

		if (_pc.getClanid() != 0) {
			weaponDamage += getDamageUpByClan(_pc);// 血盟技能傷害提升
		}
		switch (_pc.guardianEncounter()) {
		case 3:// 邪惡的守護 Lv.1
			weaponDamage += 1;
			break;
			
		case 4:// 邪惡的守護 Lv.2
			weaponDamage += 3;
			break;
			
		case 5:// 邪惡的守護 Lv.3
			weaponDamage += 5;
			break;
		}
		return weaponDamage;
	}

	/**
	 * 傷害質最終計算
	 * @param weaponTotalDamage
	 * @return
	 */
	private double weaponDamage2(double weaponTotalDamage) {
		double dmg = 0.0;
		boolean doubleBrake = false;// 技能(雙重破壞)
		switch (_weaponType2) {
		case 1:// 劍
		case 2:// 匕首
		case 3:// 雙手劍
		case 5:// 矛(雙手)
		case 6:// 斧(單手)
		case 7:// 魔杖
		case 8:// 飛刀
		case 9:// 箭
		case 14:// 矛(單手)
		case 15:// 雙手斧
		case 16:// 魔杖(雙手)
		case 18:// 鎖鏈劍
			dmg = weaponTotalDamage + _statusDamage + _pc.getDmgup() + _pc.getOriginalDmgup();
			break;

		case 11:// 鋼爪
			// 技能(雙重破壞)
			if (_pc.hasSkillEffect(DOUBLE_BRAKE)) {
				doubleBrake = true;
			}
			dmg = weaponTotalDamage + _statusDamage + _pc.getDmgup() + _pc.getOriginalDmgup();
			dmg += 5.0;
			break;
			
		case 12:// 雙刀
			// 雙擊
			if ((_random.nextInt(100) + 1) <= _weaponDoubleDmgChance) {
				_attackType = 0x04;
			}
			
			// 技能(雙重破壞)
			if (_pc.hasSkillEffect(DOUBLE_BRAKE)) {
				doubleBrake = true;
			}
			dmg = weaponTotalDamage + _statusDamage + _pc.getDmgup() + _pc.getOriginalDmgup();
			break;
			
		case 0:// 空手
			dmg = (_random.nextInt(5) + 4) >> 2;// / 4;
			break;
			
		case 4:// 弓
		case 13:// 弓(單手)
			double add = _statusDamage;
			switch (_calcType) {
			case PC_PC:
				add *= 2.5D;
				break;

			case PC_NPC:
				add *= 1.5D;
				break;
			}
			dmg = weaponTotalDamage + add + _pc.getBowDmgup() + _pc.getOriginalBowDmgup();
			if (_arrow != null) {
				final int add_dmg = Math.max(_arrow.getItem().getDmgSmall(), 1);
				dmg = dmg + _random.nextInt(add_dmg) + 1;
				
			} else if (_weaponId == 190) { // 沙哈之弓
				dmg = dmg + _random.nextInt(15) + 1;
			}
			break;

		case 10:// 鐵手甲
			dmg = weaponTotalDamage + _statusDamage + _pc.getBowDmgup() + _pc.getOriginalBowDmgup();
			final int add_dmg = Math.max(_arrow.getItem().getDmgSmall(), 1);
			dmg = dmg + _random.nextInt(add_dmg) + 1;
			break;

		case 17:// 奇古獸
			dmg += weaponTotalDamage;
			dmg += L1WeaponSkill.getKiringkuDamage(_pc, _target);
			break;
		}
		
		// 技能(雙重破壞)
		if (doubleBrake) {
			if ((_random.nextInt(100) + 1) <= 23) {
				dmg *= 1.80;// 2010-11-26(1.89)
			}
		}
		
		if (_weaponType2 != 0) {
			final int add_dmg = _weapon.getItem().get_add_dmg();
			if (add_dmg != 0) {
				dmg += add_dmg;
			}
		}
		return dmg;
	}

	/**
	 * PC基礎傷害提昇計算
	 * @param dmg
	 * @param weaponTotalDamage
	 * @return
	 */
	private double pcDmgMode(double dmg, double weaponTotalDamage) {
		
		dmg = calcBuffDamage(dmg);

		dmg += weaponSkill(_pc, _target, weaponTotalDamage);// 武器附加魔法

		addPcPoisonAttack(_target);

		if ((_weaponType != 20) && (_weaponType != 62)) { // 防具追加傷害
			dmg += _pc.getDmgModifierByArmor();
			
		} else {
			dmg += _pc.getBowDmgModifierByArmor();
		}

		dmg += dmgUp();
		dmg += dk_dmgUp();
		switch (_pc.get_weaknss()) {
		case 1:
		case 2:
			if (_pc.isFoeSlayer()) {// 使用屠宰者
				_pc.set_weaknss(0, 0);
				_pc.sendPackets(new S_PacketBoxDk(0));
			}
			break;
		case 3:
			if (_pc.isFoeSlayer()) {// 使用屠宰者
				_pc.set_weaknss(0, 0);
				_pc.sendPackets(new S_PacketBoxDk(0));
				dmg *= 1.3D;
			}
			break;
		}
		return dmg;
	}

	/**
	 * PC對PC傷害計算
	 */
	public int calcPcDamage() {
		if (_targetPc == null) {
			return 0;
		}
		
		// 傷害為0
		if (dmg0(_targetPc)) {
			_isHit = false;
			_drainHp = 0;
			return 0;
		}

		if (!_isHit) {
			return 0;
		}
		
		final int weaponMaxDamage = _weaponSmall;

		// 傷害直初始化
		int weaponDamage = weaponDamage1(weaponMaxDamage);

		if (_pc.is_mazu()) {// 媽祖祝福
			weaponDamage += 1;
		}

		double weaponTotalDamage = weaponDamage + _weaponAddDmg + _weaponEnchant;

		weaponTotalDamage += calcAttrEnchantDmg(); // 屬性強化

		// 傷害直最終計算
		double dmg = weaponDamage2(weaponTotalDamage);

		// PC基礎傷害提昇計算
		dmg = pcDmgMode(dmg, weaponTotalDamage);

		dmg -= calcPcDefense();// 被攻擊者防禦力傷害直減低
		
		dmg -= _targetPc.getDamageReductionByArmor(); // 被攻擊者防具額外傷害減免

		dmg -= _targetPc.dmgDowe(); // 機率傷害減免

		if (_targetPc.getClanid() != 0) {
			dmg -= getDamageReductionByClan(_targetPc);// 被攻擊者血盟技能傷害減免
		}

		// 增幅防禦
		if (_targetPc.hasSkillEffect(REDUCTION_ARMOR)) {
			final int targetPcLvl = Math.max(_targetPc.getLevel(), 50);
			dmg -= (targetPcLvl - 50) / 5 + 10;
		}
		
		// TODO 大豪	
		//格蘭肯 一階段 - 血量低於15%以下減傷 +20
		// final int rnd = (int) (Math.random() * 100);// 隨機數字範圍0~99   尚未使用的RND
		if (_targetPc.getLevelClass() == 1 &&(_targetPc.getCurrentHp() < _targetPc.getMaxHp()*0.2)) {
			dmg -= 20;
		}
		
		//殷海薩 一階段 - 血量低於15%以下傷害 +20
	    if (_pc.getLevelClass() == 2 &&(_pc.getCurrentHp() < _pc.getMaxHp()*0.2)) {
	    	// (電)組合動畫效果
			int x = _targetPc.getX();
			int y = _targetPc.getY();
			int mapId = _targetPc.getMapId();
			
			_targetPc.sendPackets(new S_EffectLocation(new L1Location(
					x - 2, y - 2, mapId), 4842));
			_targetPc.sendPackets(new S_EffectLocation(new L1Location(
					x + 2, y - 2, mapId), 4842));
			_targetPc.sendPackets(new S_EffectLocation(new L1Location(
					x + 2, y + 2, mapId), 4842));
			_targetPc.sendPackets(new S_EffectLocation(new L1Location(
					x - 2, y + 2, mapId), 4842));
	    }
	    
		boolean dmgX2 = false;// 傷害除2
		// 取回技能
		if (!_targetPc.getSkillisEmpty() && _targetPc.getSkillEffect().size() > 0) {
			try {
				for (final Integer key : _targetPc.getSkillEffect()) {
					final Integer integer = L1AttackList.SKD3.get(key);
					if (integer != null) {
						if (integer.equals(key)) {
							dmgX2 = true;
							
						} else {
							dmg += integer;
						}
					}
				}
				
			} catch (final ConcurrentModificationException e) {
				// 技能取回發生其他線程進行修改
			} catch (final Exception e) {
				_log.error(e.getLocalizedMessage(), e);
			}
		}

		if (dmgX2) {
			dmg /= 2;
		}

		// 魔法娃娃特殊技能
		if (!_pc.getDolls().isEmpty()) {
			for (final Iterator<L1DollInstance> iter = _pc.getDolls().values().iterator(); iter.hasNext();) {
				final L1DollInstance doll = iter.next();
				doll.startDollSkill(_targetPc, dmg);
			}
		}

		// 雙刀重擊
		if (_attackType == 0x04) {
			dmg *= 1.80;// 2010-11-26(1.89)
		}
		
		dmg *= coatArms();
		
		// 未命中傷害歸0
		if (!this._isHit) {
			dmg = 0.0;
		}

		if (dmg <= 0) {
			_isHit = false;
			_drainHp = 0;
		}

		//System.out.println("PC對PC傷害 武器系統:" + dmg);
		return (int) dmg;
	}

	/**
	 * PC對NPC傷害
	 * @return
	 */
	private int calcNpcDamage() {
		if (_targetNpc == null) {
			return 0;
		}
		
		// 傷害為0
		if (dmg0(_targetNpc)) {
			_isHit = false;
			_drainHp = 0;
			return 0;
		}

		if (!_isHit) {
			return 0;
		}
		
		int weaponMaxDamage = 0;
		if (_targetNpc.getNpcTemplate().isSmall() && (_weaponSmall > 0)) {
			if (_weaponSmall > 0) {
				weaponMaxDamage = _weaponSmall;
			}
			
		} else if (_targetNpc.getNpcTemplate().isLarge() && (_weaponLarge > 0)) {
			if (_weaponLarge > 0) {
				weaponMaxDamage = _weaponLarge;
			}
			
		} else {
			if (_weaponSmall > 0) {
				weaponMaxDamage = _weaponSmall;
			}
		}
		// 傷害直初始化
		int weaponDamage = weaponDamage1(weaponMaxDamage);

		if (_pc.is_mazu()) {// 媽祖祝福
			weaponDamage += 1;
		}

		double weaponTotalDamage = weaponDamage + _weaponAddDmg + _weaponEnchant;

		weaponTotalDamage += calcMaterialBlessDmg(); // 祝福武器 銀/米索莉/奧里哈魯根材質武器

		weaponTotalDamage += calcAttrEnchantDmg(); // 属性強化

		// 傷害直最終計算
		double dmg = weaponDamage2(weaponTotalDamage);

		// PC基礎傷害提昇計算
		dmg = pcDmgMode(dmg, weaponTotalDamage);

		dmg -= calcNpcDamageReduction();// NPC防禦力額外傷害減低

		// プレイヤーからペット、サモンに攻撃
		boolean isNowWar = false;
		final int castleId = L1CastleLocation.getCastleIdByArea(_targetNpc);
		if (castleId > 0) {
			isNowWar = ServerWarExecutor.get().isNowWar(castleId);
		}
		
		if (!isNowWar) {
			if (_targetNpc instanceof L1PetInstance) {
				dmg /= 8;
			}
			if (_targetNpc instanceof L1SummonInstance) {
				final L1SummonInstance summon = (L1SummonInstance) _targetNpc;
				if (summon.isExsistMaster()) {
					dmg /= 8;
				}
			}
		}

		// 魔法娃娃特殊技能
		if (!_pc.getDolls().isEmpty()) {
			for (final Iterator<L1DollInstance> iter = _pc.getDolls().values().iterator(); iter.hasNext();) {
				final L1DollInstance doll = iter.next();
				doll.startDollSkill(_targetNpc, dmg);
			}
		}

		// 雙刀重擊
		if (_attackType == 0x04) {
			dmg *= 1.80;// 2010-11-26(1.89)
		}
		
		// 未命中傷害歸0
		if (!_isHit) {
			dmg = 0D;
		}
		
		if (dmg <= 0D) {
			_isHit = false;
			_drainHp = 0; // ダメージ無しの場合は吸収による回復はしない
		}
		
		//System.out.println("PC對NPC傷害 武器系統:" + dmg);
		return (int) dmg;
	}
	
	private int dk_dmgUp() {
		int dmg = 0;
		if (_pc.isDragonKnight() && _weaponType2 == 18) {// 鎖鍊劍
			long h_time = Calendar.getInstance().getTimeInMillis() / 1000;// 換算為秒
			switch (_pc.get_weaknss()) {
			case 0:
				if (_pc.isFoeSlayer()) {// 使用屠宰者
					return 0;
				}
				if ((_random.nextInt(100)) < 20) {
					_pc.set_weaknss(1, h_time);
					_pc.sendPackets(new S_PacketBoxDk(S_PacketBoxDk.LV1));
					dmg += 20;
				}
				break;
			case 1:
				if (_pc.isFoeSlayer()) {// 使用屠宰者
					return 0;
				}
				if ((_random.nextInt(100)) < 60) {
					_pc.set_weaknss(1, h_time);
					_pc.sendPackets(new S_PacketBoxDk(S_PacketBoxDk.LV1));
					dmg += 20;
				} else {
					_pc.set_weaknss(2, h_time);
					_pc.sendPackets(new S_PacketBoxDk(S_PacketBoxDk.LV2));
					dmg += 40;
				}
				break;
			case 2:
				if (_pc.isFoeSlayer()) {// 使用屠宰者
					return 0;
				}
				if ((_random.nextInt(100)) < 60) {
					_pc.set_weaknss(2, h_time);
					_pc.sendPackets(new S_PacketBoxDk(S_PacketBoxDk.LV2));
					dmg += 40;
				} else {
					_pc.set_weaknss(3, h_time);
					_pc.sendPackets(new S_PacketBoxDk(S_PacketBoxDk.LV3));
					dmg += 60;
				}
				break;
			case 3:
				if (_pc.isFoeSlayer()) {// 使用屠宰者
					return 0;
				}
				if ((_random.nextInt(100)) < 20) {
					_pc.set_weaknss(3, h_time);
					_pc.sendPackets(new S_PacketBoxDk(S_PacketBoxDk.LV3));
					dmg += 60;
				}
				break;
			}
		}
		return dmg;
	}

	/**
	 * 技能對武器追加傷害
	 * @return
	 */
	private double dmgUp() {
		double dmg = 0.0;
		
		if (_pc.getSkillEffect().size() <= 0) {
			return dmg;
		}

		if (!_pc.getSkillisEmpty()) {
			try {
				HashMap<Integer, Integer> skills = null;
				switch (_weaponType) {
				case 20:// 弓
				case 62:// 鐵手甲
					skills = L1AttackList.SKD2;
					break;

				case 24:// 鎖鍊劍
				default:
					skills = L1AttackList.SKD1;
					break;
				}

				if (skills != null) {
					for (final Integer key : _pc.getSkillEffect()) {
						final Integer integer = L1AttackList.SKD2.get(key);
						if (integer != null) {
							dmg += integer;
						}
					}
				}
				
			} catch (final ConcurrentModificationException e) {
				// 技能取回發生其他線程進行修改
			} catch (final Exception e) {
				_log.error(e.getLocalizedMessage(), e);
			}
		}
		dmg += _pc.dmgAdd();
		return dmg;
	}

	/**
	 * 武器附加魔法
	 * @param pcInstance
	 * @param character
	 * @param weaponTotalDamage 
	 * @return
	 */
	private double weaponSkill(final L1PcInstance pcInstance, final L1Character character, double weaponTotalDamage) {
		double dmg = 0D;

		switch (_weaponId) {
		case 265:// 底比斯歐西裡斯雙刀
		case 266:// 底比斯歐西裡斯雙手劍
		case 267:// 底比斯歐西裡斯弓
		case 268:// 底比斯歐西裡斯魔杖
			// dmg = L1WeaponSkill.getChaserDamage(_pc, _target);
			break;

		case 2:// 骰子匕首
		case 200002:// 骰子匕首
			if (this._targetPc != null) {
				dmg = L1WeaponSkill.getDiceDaggerDamage(_pc, _targetPc, _weapon);
			}
			break;

		case 124:// 巴風特魔杖
			dmg = L1WeaponSkill.getBaphometStaffDamage(_pc, _target);
			break;

		case 204:// 深紅之弩
		case 100204:// 深紅之弩
			L1WeaponSkill.giveFettersEffect(_pc, _target);
			break;

		case 261:// 大法師魔仗
			L1WeaponSkill.giveArkMageDiseaseEffect(_pc, _target);
			break;

		case 260:// 狂風之斧
		case 263:// 酷寒之矛
			dmg = L1WeaponSkill.getAreaSkillWeaponDamage(_pc, _target, _weaponId);
			break;

		case 264:// 雷雨之劍
			dmg = L1WeaponSkill.getLightningEdgeDamage(_pc, _target);
			break;


		case 262: // 毀滅巨劍HP奪取成功確率(暫定)75%
			final int random = _random.nextInt(110) + 1;
			if (random <= 75) {
				dmg = calcDestruction(weaponTotalDamage);
			}
			break;
			
		default:
			dmg = L1WeaponSkill.getWeaponSkillDamage(_pc, _target, _weaponId);
			break;
		}

		return dmg;
	}

	/**
	 * 武器強化魔法
	 * @param dmg
	 * @return
	 */
	private double calcBuffDamage(double dmg) {
		if (_weaponType == 20) {// 弓
			return dmg;
		}
		if (_weaponType == 62) {// 鐵手甲
			return dmg;
		}
		if (_weaponType2 == 17) {// 奇古獸
			return dmg;
		}
		
		boolean isDmgUp = false;
		double dmgDouble = 1.0;
		final int random = _random.nextInt(100) + 1;
		
		// 屬性之火
		if (_pc.hasSkillEffect(ELEMENTAL_FIRE)) {
			if (random <= 33) {
				isDmgUp = true;
				dmgDouble += 0.6;// 2011-10-13(0.5)
			}
		}
		
		// 燃燒鬥志
		if (_pc.hasSkillEffect(BURNING_SPIRIT)) {
			if (random <= 33) {
				isDmgUp = true;
				dmgDouble += 0.40;// 2010-11-26(0.45)
			}
		}
		
		// 烈焰之魂
		if (_pc.hasSkillEffect(SOUL_OF_FLAME)) {
			if (random <= 33) {
				isDmgUp = true;
				dmgDouble += 0.7;// 2011-10-13(5)
			}
		}
		
		if (isDmgUp) {
			double tempDmg = dmg;
			// 火焰武器
			if (_pc.hasSkillEffect(FIRE_WEAPON)) {
				tempDmg -= 4;
			}
			
			// 烈炎氣息
			if (_pc.hasSkillEffect(FIRE_BLESS)) {
				tempDmg -= 4;
			}
			
			// 烈炎武器
			if (_pc.hasSkillEffect(BURNING_WEAPON)) {
				tempDmg -= 6;
			}
			
			// 狂暴術
			if (_pc.hasSkillEffect(BERSERKERS)) {
				tempDmg -= 5;
			}
			final double diffDmg = dmg - tempDmg;
			dmg = (tempDmg * dmgDouble) + diffDmg;
		}
		return dmg;
	}

	/**
	 * 祝福武器 銀/米索莉/奧里哈魯根材質武器<BR>
	 * 其他屬性定義
	 * @return
	 */
	private int calcMaterialBlessDmg() {
		int damage = 0;
		if (_pc.getWeapon() != null) {
			final int undead = _targetNpc.getNpcTemplate().get_undead();
			switch (undead) {
			case 1:// 不死系
				if ((_weaponMaterial == 14) || (_weaponMaterial == 17) || (_weaponMaterial == 22)) {// 銀/米索莉/奧里哈魯根
					damage += _random.nextInt(20) + 1;
				}
				if (_weaponBless == 0) { // 祝福武器
					damage += _random.nextInt(4) + 1;
				}
				switch (_weaponType) {
				case 20:
				case 62:
					break;
				default:
					if (_weapon.getHolyDmgByMagic() != 0) {
						damage += _weapon.getHolyDmgByMagic();// 武器強化魔法
					}
					break;
				}
				break;
			case 2:// 惡魔系
				if ((_weaponMaterial == 17) || (_weaponMaterial == 22)) {// 米索莉/奧里哈魯根
					damage += _random.nextInt(3) + 1;
				}
				if (_weaponBless == 0) { // 祝福武器
					damage += _random.nextInt(4) + 1;
				}
				break;
			case 3:// 殭屍系
				if ((_weaponMaterial == 14) || (_weaponMaterial == 17) || (_weaponMaterial == 22)) {// 銀/米索莉/奧里哈魯根
					damage += _random.nextInt(20) + 1;
				}
				if (_weaponBless == 0) { // 祝福武器
					damage += _random.nextInt(4) + 1;
				}
				switch (_weaponType) {
				case 20:
				case 62:
					break;
				default:
					if (_weapon.getHolyDmgByMagic() != 0) {
						damage += _weapon.getHolyDmgByMagic();// 武器強化魔法
					}
					break;
				}
				break;
			case 5:// 狼人系
				if ((_weaponMaterial == 14) || (_weaponMaterial == 17) || (_weaponMaterial == 22)) {// 銀/米索莉/奧里哈魯根
					damage += _random.nextInt(20) + 1;
				}
				break;
			}
		}
		return damage;
	}

	/**
	 * 武器の属性強化による追加ダメージ算出
	 * @return
	 */
	private int calcAttrEnchantDmg() {
		int damage = 0;
		switch (this._weaponAttrEnchantLevel) {
		case 1:
			damage = 1;
			break;

		case 2:
			damage = 3;
			break;

		case 3:
			damage = 5;
			break;
		}

		// 對地火火風抗性的處理
		int resist = 0;
		switch (this._calcType) {
		case PC_PC:
			switch (this._weaponAttrEnchantKind) {
			case 1: // 地
				resist = this._targetPc.getEarth();
				break;

			case 2: // 火
				resist = this._targetPc.getFire();
				break;

			case 4: // 水
				resist = this._targetPc.getWater();
				break;

			case 8: // 風
				resist = this._targetPc.getWind();
				break;
				
			case 16: // 光
				resist = this._targetPc.getEarth();
				break;
				
			case 32: // 暗
				resist = this._targetPc.getFire();
				break;
				
			case 64: // 聖
				resist = this._targetPc.getWater();
				break;
				
			case 128: // 邪
				resist = this._targetPc.getWind();
				break;
			}
			break;

		case PC_NPC:
			switch (this._weaponAttrEnchantKind) {
			case 1: // 地
				resist = this._targetNpc.getEarth();
				break;

			case 2: // 火
				resist = this._targetNpc.getFire();
				break;

			case 4: // 水
				resist = this._targetNpc.getWater();
				break;

			case 8: // 風
				resist = this._targetNpc.getWind();
				break;
				
			case 16: // 光
				resist = this._targetNpc.getEarth();
				break;
				
			case 32: // 暗
				resist = this._targetNpc.getFire();
				break;
				
			case 64: // 聖
				resist = this._targetNpc.getWater();
				break;
				
			case 128: // 邪
				resist = this._targetNpc.getWind();
				break;
			}
			break;
		}

		int resistFloor = (int) (0.32 * Math.abs(resist));

		if (resist < 0) {
			resistFloor *= -1;
		}
		
		final double attrDeffence = resistFloor / 32.0;
		final double attrCoefficient = 1 - attrDeffence;

		damage *= attrCoefficient;

		return damage;
	}

	/**
	 * 魔力奪取武器 MP奪取質計算
	 */
	@Override
	public void calcStaffOfMana() {
		switch (this._weaponId) {
		case 126: // 瑪那魔杖
		case 127: // 鋼鐵瑪那魔杖
			int som_lvl = this._weaponEnchant + 3; // 最大MP吸収量を設定
			if (som_lvl < 0) {
				som_lvl = 0;
			}
			// MP修收量取得(最大吸收9)
			this._drainMana = Math.min(_random.nextInt(som_lvl) + 1, 9);
			break;

		case 259: // 魔力短劍
			switch (this._calcType) {
			case PC_PC:
				if (this._targetPc.getMr() <= _random.nextInt(100) + 1) { // 確率はターゲットのMRに依存
					this._drainMana = 1; // 吸収量は1固定
				}
				break;

			case PC_NPC:
				if (this._targetNpc.getMr() <= _random.nextInt(100) + 1) { // 確率はターゲットのMRに依存
					this._drainMana = 1; // 吸収量は1固定
				}
				break;
			}
			break;
		}
	}

	/**
	 * HP吸収量算出
	 * @param dmg
	 * @return
	 */
	private double calcDestruction(final double dmg) {
		// HP吸収量(最小1)
		_drainHp = Math.max((int) ((dmg / 8) + 1), 1);
		return _drainHp;
	}

	/**
	 * PC附加毒性攻擊
	 * @param attacker
	 * @param target
	 */
	private void addPcPoisonAttack(final L1Character target) {
		boolean isCheck = false;
		switch (_weaponId) {
		case 0:// 空手
			break;
			
		case 13:// 死亡之指
		case 14:// 混沌之刺
			isCheck = true;
			break;
			
		default:
			if (_pc.hasSkillEffect(ENCHANT_VENOM)) {
				isCheck = true;
			}
			break;
		}
		
		if (isCheck) {
			final int chance = _random.nextInt(100) + 1;
			if (chance <= 10) {
				// 通常毒、3秒周期、ダメージHP-5
				L1DamagePoison.doInfection(_pc, target, 3000, 5);
			}
		}
	}

	/**
	 * 底比斯武器魔法的效果
	 */
	@Override
	public void addChaserAttack() {
		int mr = 0;
		switch (_calcType) {
		case PC_PC:
			mr = _targetPc.getMr() - (2 * _pc.getOriginalMagicHit());
			break;

		case PC_NPC:
			mr = _targetNpc.getMr() - (2 * _pc.getOriginalMagicHit());
			break;
		}

		double probability = 3 + (_pc.getTrueSp() * 0.25);
		probability -= (mr / 10) * 0.1;

		switch (_weaponId) {
		case 265:// 底比斯歐西裡斯雙刀
		case 266:// 底比斯歐西裡斯雙手劍
		case 267:// 底比斯歐西裡斯弓
		case 268:// 底比斯歐西裡斯魔杖
			if ((probability / 1.1) > _random.nextInt(100) + 1) {
				final L1Chaser chaser = new L1Chaser(_pc, _target);
				chaser.begin();
			}
			break;
		}
	}

	/**
	 * 攻擊資訊送出
	 */
	@Override
	public void action() {
		try {
			if (_pc == null) {
				return;
			}
			if (_target == null) {
				return;
			}
			// 改變面向
			_pc.setHeading(_pc.targetDirection(_targetX, _targetY));
			
			if (_weaponRange == -1) {// 遠距離武器
				actionX1();
				
			} else {// 近距離武器
				actionX2();
			}
			
		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}
	}

	/**
	 * 近距離武器/空手
	 */
	private void actionX2() {
		try {
			if (_isHit) {// 命中
				//System.out.println("命中");
				_pc.sendPacketsX10(
						new S_AttackPacketPc(
								_pc, 
								_target, 
								_attackType, 
								_damage
								));
				
			} else {// 未命中
				if (_targetId > 0) {
					_pc.sendPacketsX10(
							new S_AttackPacketPc(_pc, _target));

				} else {
					_pc.sendPacketsAll(new S_AttackPacketPc(_pc));
				}
			}
			
		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}
	}

	/**
	 * 遠距離武器
	 */
	private void actionX1() {
		try {
			switch (_weaponType) {
			case 20:// 弓
				switch (_weaponId) {
				case 190: // 沙哈之弓 不具有箭
					if (_arrow != null) { // 具有箭
						_pc.getInventory().removeItem(_arrow, 1);
					}
					_pc.sendPacketsX10(
							new S_UseArrowSkill(
									_pc, 
									_targetId, 
									2349, 
									_targetX, 
									_targetY, 
									_damage
									));
					break;
					
				default:// 其他武器 沒有箭
					if (_arrow != null) { // 具有箭
						int arrowGfxid = 66;
						switch (_pc.getTempCharGfx()) {
						case 8842:
						case 8900:// 海露拜
							arrowGfxid = 8904;// 黑
							break;
							
						case 8913:
						case 8845:// 朱里安
							arrowGfxid = 8916;// 白
							break;
							
						case 7959:
						case 7967:
						case 7968:
						case 7969:
						case 7970:// 天上騎士
							arrowGfxid = 7972;// 火
							break;
						}
						_pc.sendPacketsX10(
								new S_UseArrowSkill(
										_pc, 
										_targetId, 
										arrowGfxid, 
										_targetX, 
										_targetY, 
										_damage
										));
						_pc.getInventory().removeItem(_arrow, 1);
						
					} else {
						int aid = 1;
						// 外型編號改變動作
						if (_pc.getTempCharGfx() == 3860) {
							aid = 21;
						}
						_pc.sendPacketsAll(new S_ChangeHeading(_pc));
						// 送出封包(動作)
						_pc.sendPacketsAll(
								new S_DoActionGFX(
										_pc.getId(), 
										aid
										));
					}
				}
				break;

			case 62: // 鐵手甲
				if (_sting != null) {// 具有飛刀
					int stingGfxid = 2989;
					switch (_pc.getTempCharGfx()) {
					case 8842:
					case 8900:// 海露拜
						stingGfxid = 8904;// 黑
						break;
						
					case 8913:
					case 8845:// 朱里安
						stingGfxid = 8916;// 白
						break;
						
					case 7959:
					case 7967:
					case 7968:
					case 7969:
					case 7970:// 天上騎士
						stingGfxid = 7972;// 火
						break;
					}
					_pc.sendPacketsX10(
							new S_UseArrowSkill(
									_pc, 
									_targetId, 
									stingGfxid, 
									_targetX, 
									_targetY, 
									_damage
									));
					_pc.getInventory().removeItem(_sting, 1);
					
				} else {// 沒有飛刀
					int aid = 1;
					// 外型編號改變動作
					if (_pc.getTempCharGfx() == 3860) {
						aid = 21;
					}
					
					_pc.sendPacketsAll(new S_ChangeHeading(_pc));
					// 送出封包(動作)
					_pc.sendPacketsAll(
							new S_DoActionGFX(
									_pc.getId(), 
									aid
									));
				}
				break;
			}
			
		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}
	}

	/**
	 * 計算結果
	 */
	@Override
	public void commit() {
		if (_isHit) {
			switch (_calcType) {
			case PC_PC:
				commitPc();
				break;

			case PC_NPC:
				commitNpc();
				break;
			}
		}
		
		// gm攻擊資訊
		if (!ConfigAlt.ALT_ATKMSG) {
			return;
			
		} else {
			switch (_calcType) {
			case PC_PC:
				if (!_pc.isGm()) {
					if (!_targetPc.isGm()) {
						return;
					}
				}
				break;

			case PC_NPC:
				if (!_pc.isGm()) {
					return;
				}
				break;
			}
		}

		final String srcatk = _pc.getName();// 攻擊者
		String tgatk = "";// 被攻擊者
		String hitinfo = "";// 資訊
		String dmginfo = "";// 傷害
		String x = "";// 最終資訊

		switch (this._calcType) {
		case PC_PC:
			tgatk = _targetPc.getName();
			hitinfo = " 命中:" + _hitRate + "% 剩餘hp:" + _targetPc.getCurrentHp();
			dmginfo = _isHit ? "傷害:" + _damage : "失敗";
			x = srcatk + ">" + tgatk + " " + dmginfo + hitinfo;
			if (_pc.isGm()) {
				// 166 \f1%0%s %4%1%3 %2。
				_pc.sendPackets(new S_ServerMessage(166, "對PC送出攻擊: " + x));
			}
			
			if (_targetPc.isGm()) {
				// 166 \f1%0%s %4%1%3 %2。
				_targetPc.sendPackets(new S_ServerMessage(166, "受到PC攻擊: " + x));
			}
			break;

		case PC_NPC:
			tgatk = this._targetNpc.getName();
			hitinfo = " 命中:" + this._hitRate + "% 剩餘hp:" + this._targetNpc.getCurrentHp();
			dmginfo = this._isHit ? "傷害:" + this._damage : "失敗";
			x = srcatk + ">" + tgatk + " " + dmginfo + hitinfo;
			if (this._pc.isGm()) {
				// 166 \f1%0%s %4%1%3 %2。
				this._pc.sendPackets(new S_ServerMessage(166, "對NPC送出攻擊: " + x));
			}
			break;
		}
	}

	/**
	 * 對PC攻擊傷害結果
	 */
	private void commitPc() {
		if ((_drainMana > 0) && (_targetPc.getCurrentMp() > 0)) {
			if (_drainMana > _targetPc.getCurrentMp()) {
				_drainMana = _targetPc.getCurrentMp();
			}
			short newMp = (short) (_targetPc.getCurrentMp() - _drainMana);
			_targetPc.setCurrentMp(newMp);
			newMp = (short) (this._pc.getCurrentMp() + _drainMana);
			_pc.setCurrentMp(newMp);
		}
		
		if (_drainHp > 0) { // HP吸收回復
			final short newHp = (short) (_pc.getCurrentHp() + _drainHp);
			_pc.setCurrentHp(newHp);
		}
		
		damagePcWeaponDurability(); // 武器受到傷害
		_targetPc.receiveDamage(_pc, _damage, false, false);
	}

	/**
	 * 對NPC攻擊傷害結果
	 */
	private void commitNpc() {
		if (_drainMana > 0) {
			final int drainValue = _targetNpc.drainMana(_drainMana);
			final int newMp = _pc.getCurrentMp() + drainValue;
			_pc.setCurrentMp(newMp);
			if (drainValue > 0) {
				final int newMp2 = _targetNpc.getCurrentMp() - drainValue;
				_targetNpc.setCurrentMpDirect(newMp2);
			}
		}
		
		if (this._drainHp > 0) { // HP吸收回復
			final short newHp = (short) (_pc.getCurrentHp() + _drainHp);
			_pc.setCurrentHp(newHp);
		}
		
		damageNpcWeaponDurability(); // 武器受到傷害
		_targetNpc.receiveDamage(_pc, _damage);
	}

	/**
	 * 相手の攻撃に対してカウンターバリアが有効かを判別
	 */
	@Override
	public boolean isShortDistance() {
		boolean isShortDistance = true;
		if ((_weaponType == 20) || (_weaponType == 62)) { // 弓かガントレット
			isShortDistance = false;
		}
		return isShortDistance;
	}

	/**
	 * 反擊屏障的傷害反擊
	 */
	@Override
	public void commitCounterBarrier() {
		final int damage = calcCounterBarrierDamage();
		if (damage == 0) {
			return;
		}
		// 受傷動作
		_pc.sendPacketsAll(
				new S_DoActionGFX(
						_pc.getId(), 
						ActionCodes.ACTION_Damage
						));
		_pc.receiveDamage(_target, damage, false, true);
	}

	/**
	 * 武器受到傷害 対NPCの場合、損傷確率は10%とする。祝福武器は3%とする。
	 */
	private void damageNpcWeaponDurability() {
		/*
		 * 損傷しないNPC、素手、損傷しない武器使用、SOF中の場合何もしない。
		 */
		if (this._calcType != PC_NPC) {
			return;
		}
		
		if (this._targetNpc.getNpcTemplate().is_hard() == false) {
			return;
		}
		
		if (this._weaponType == 0) {
			return;
		}
		
		if (this._weapon.getItem().get_canbedmg() == 0) {
			return;
		}
		
		if (this._pc.hasSkillEffect(SOUL_OF_FLAME)) {
			return;
		}

		final int random = _random.nextInt(100) + 1;
		switch (this._weaponBless) {
		case 0:// 祝福
			if (random < 3) {
				// \f1你的%0%s壞了。
				this._pc.sendPackets(new S_ServerMessage(268, this._weapon.getLogName()));
				this._pc.getInventory().receiveDamage(this._weapon);
			}
			break;
			
		case 1:// 一般
		case 2:// 詛咒
			if (random < 10) {
				// \f1你的%0%s壞了。
				this._pc.sendPackets(new S_ServerMessage(268, this._weapon.getLogName()));
				this._pc.getInventory().receiveDamage(this._weapon);
			}
			break;
		}
	}

	/**
	 * バウンスアタックにより武器受到傷害 バウンスアタックの損傷確率は10%
	 */
	private void damagePcWeaponDurability() {
		if (this._calcType != PC_PC) {
			return;
		}
		
		if (this._weaponType == 0) {
			return;
		}
		
		if (this._weaponType == 20) {
			return;
		}
		
		if (this._weaponType == 62) {
			return;
		}
		
		if (this._targetPc.hasSkillEffect(BOUNCE_ATTACK) == false) {
			return;
		}
		
		if (this._pc.hasSkillEffect(SOUL_OF_FLAME)) {
			return;
		}
		
		if (_random.nextInt(100) + 1 <= 10) {
			// \f1你的%0%s壞了。
			this._pc.sendPackets(new S_ServerMessage(268, this._weapon.getLogName()));
			this._pc.getInventory().receiveDamage(this._weapon);
		}
	}
}
